--[[	$Id: macros.lua 3938 2014-10-19 11:47:53Z sdkyron@gmail.com $	]]

local _, caelUI = ...

caelUI.macros = caelUI.createModule("Macros")

LoadAddOn("Blizzard_MacroUI")
local macros = gM_Macros

local buttons = {}
local prefix = "gotMacros_"

local QUESTION_MARK_ICON = "INV_MISC_QUESTIONMARK"

local function NoSoundPreClick()
	SetCVar("Sound_EnableSFX", 0)
end

local function NoSoundPostClick()
	SetCVar("Sound_EnableSFX", 1)
end

local function LevelConditional(wholeMatch)
	local levelComparison, positiveCase, negativeCase = wholeMatch:match("lvl{(.-)?(.-):(.+)}")
	if (loadstring("return " .. UnitLevel("player") .. levelComparison)()) then
		return positiveCase
	else
		return negativeCase
	end
end

local function ParseEscapeSequences(text)
	text = text:gsub("(lvl%b{})", LevelConditional)
	text = text:gsub("sid{(%d+)}", GetSpellInfo)
	text = text:gsub("iid{(%d+)}", GetItemInfo)
	return text
end

local function SetUpMacro(name, body, nosound)
	local btn = buttons[name]
	if not btn then
		btn = CreateFrame("Button", prefix..name, UIParent, "SecureUnitButtonTemplate")
		buttons[name] = btn
	end

	if nosound then
		btn:SetScript("PreClick", NoSoundPreClick)
		btn:SetScript("PostClick", NoSoundPostClick)
	end

	if body:len() > 1023 then
		print("Gotai is lazy, no macros longer than 1023 chars plx!")
	end

	btn:SetAttribute("type", "macro")
	btn:SetAttribute("macrotext", body)
end

local function CreateBlizzardMacro(name, perChar, icon)
	if not buttons[name] then
		return print(string.format("No button called %q could be found.", tostring(name)))
	end

	if icon then
		icon = icon:match("Interface.Icons.(.+)") or icon
	end

	local macroname = "gM_"..name:sub(1,13)
	local macrobody = string.format("/click %s", buttons[name]:GetName())
	local show = macros[name].show
	if show then
		show = string.format("#showtooltip %s\n", ParseEscapeSequences(show))
		if show:len() + macrobody:len() <= 255 then
			macrobody = show..macrobody
		end
	end

	local index = GetMacroIndexByName(macroname)
	if index > 0 then
		EditMacro(index, nil, icon or QUESTION_MARK_ICON, macrobody)
	else
		local Macros, PerCharMacros = GetNumMacros()
		if perChar and PerCharMacros >= MAX_CHARACTER_MACROS then
			perChar = nil
		end
		if not perChar and Macros >= MAX_ACCOUNT_MACROS then
			return print("Your macro slots are all full, please delete some macros and reload.")
		end
		CreateMacro(macroname, icon or QUESTION_MARK_ICON, macrobody, perChar)
	end
end

local function ValidForSpec(macroTable, spec)
	if (not spec) then
		spec = GetSpecialization()
	end

	if not macroTable.spec or (spec and macroTable.spec:find(spec)) then
		return true
	end
end

local function ValidForClass(macroTable, class)
	if (not class) then
		class = caelUI.playerClass
	end

	if (not macroTable.class or macroTable.class == class) then
		return true
	end
end

function CreateMacros()
	local NumMacros, NumMacrosPerChar = GetNumMacros()
	local playerClass = caelUI.playerClass
	local currentSpec = GetSpecialization()

	for i = NumMacros, 1, -1 do
		local name = GetMacroInfo(i):match("^gM_(.+)")
		if name and (not macros[name] or not macros[name].blizzmacro or not ValidForClass(macros[name], playerClass) or not ValidForSpec(macros[name], currentSpec)) then
			DeleteMacro(i)
		end
	end

	for i = 121 + (NumMacrosPerChar - 1 or 0), 121, -1 do
		local name = GetMacroInfo(i):match("^gM_(.+)")
		if name and (not macros[name] or not macros[name].blizzmacro or not ValidForClass(macros[name], playerClass) or not ValidForSpec(macros[name], currentSpec)) then
			DeleteMacro(i)
		end
	end

	for k,v in pairs(macros) do
		if (not v.char or v.char:find(caelUI.playerName)) and ValidForClass(v, playerClass) and ValidForSpec(v, currentSpec) then
			SetUpMacro(k, ParseEscapeSequences(v.body:gsub("\n\t*", "\n")), v.nosound)
			if v.blizzmacro then
				CreateBlizzardMacro(k, v.perChar, v.icon)
			end
		end
	end
end

caelUI.macros:RegisterEvent("PLAYER_ENTERING_WORLD")
caelUI.macros:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED")
caelUI.macros:SetScript("OnEvent", function(self, event, ...)
	if (event ~= "ACTIVE_TALENT_GROUP_CHANGED") then
		self:UnregisterEvent(event)
	end
	
	if InCombatLockdown() then
		return self:RegisterEvent("PLAYER_REGEN_ENABLED")
	end
	
	CreateMacros()
end)
--[[
local _GetActionText = GetActionText
GetActionText = function(action)
   local text = _GetActionText(action)
   if text and text:find("^gM_") then
      return text:sub(4)
   else
      return text
   end
end
--]]